/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package org.animatedalligator;

import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.DefaultListModel;
import javax.swing.JOptionPane;
import uc.edu.server.IAdvertisementEngine;
import uc.edu.server.IChatService;
import uc.edu.server.Message;
import uc.edu.server.MessageWithID;
import uc.edu.server.User;
//import uc.edu.server.Message;

/**
 *
 * @author tony
 */
public class MainFrame extends javax.swing.JFrame
{

//    static final String LINE_SEPARATOR = System.getProperty("line.separator");
    private User myMaster;
    private IChatService chatService;
    private IAdvertisementEngine adEngine;
    //sprivate ArrayList<MessageWithID> messageList;
    //private DefaultListModel messageDisplayModel;
//    private JListClientDisplay clientDisplay;

    /**
     * Inner class to handle fetching ads
     */
    private class AdvertisementRotator implements Runnable
    {
        // How often (in milliseconds) do ads get rotated:

        private static final int AD_ROTATION_INTERVAL = 10000;
        private IAdvertisementEngine adEngine = new AdvertisementEngineStub();

        /**
         * Checks server for ads every AD_ROTATION_INTERVAL milliseconds.
         * Quit if server has no more ads for us.
         * Otherwise, set text of ad display label to text of ad.
         */
        @Override
        public void run()
        {
            String ad;
            do
              {
                // get next ad from ad server
                ad = adEngine.getAdvertisement();
                // put it on label. Note that it will do no
                // harm even if ad is null.
                lblAds.setText(ad);
                try
                  {
                    Thread.sleep(AD_ROTATION_INTERVAL);
                  } catch (InterruptedException ex)
                  {
                    // put in hook here to detect and act on interrupt --
                    // that is, react properly when someone else kills this
                    // thread.
                    Logger.getLogger(MainFrame.class.getName()).log(Level.SEVERE, null, ex);
                  }
              } while (ad != null); // If getAdvertisement returns null, we're done.
        } // end of run()
    } // end class AdvertisementRotator

    /**
     * Inner class to handle getting messages from server and displaying them on
     * JFrame's display pane.
     */
    private class MessageGrabber implements Runnable
    {
        // How often (in milliseconds) do we check server
        // for messages:

        private static final int MSG_CHECK_INTERVAL = 1000;
        // max id of messages we've seen.
        private long lastMessageSeen;
        // Have we gotten any messages yet?
        private boolean noMessagesYet;

        /**
         * Constructor
         *
         * @return
         */
        public MessageGrabber()
        {
            // Initialize message display parameters:
            clearLastMessageSeen();
            noMessagesYet = true;
            //initMessageDisplay();
        }

        private long getLastMessageSeen()
        {
            return lastMessageSeen;
        }

        private void setLastMessageSeen(long newID)
        {
            lastMessageSeen = newID;
        }

        private void clearLastMessageSeen()
        {
            setLastMessageSeen(0L);
        }

        /**
         * Loops forever.
         * Each time through, calls receiveMessage(lastID) to get
         * the next message from the server that has an ID greater
         * than the highest ID we've already seen.
         * receiveMessage() will return null if there is no such
         * message.
         * If we do get a message back, tell the main frame's
         * message display area to display it.
         */
        @Override
        public void run()
        {
            while (true)
              {
                try
                  {
                    // Now call receiveMessage(). Set lastMessageSeen to
                    // id of returned message (if any)
                    MessageWithID mid = chatService.receiveMessage(getLastMessageSeen());
                    if (mid != null)
                      {
                        setLastMessageSeen(mid.getID());
                        if (noMessagesYet)
                          {
                            MainFrame.this.clientDisplay.clearMessageDisplay();
                            noMessagesYet = false;
                          }
                        MainFrame.this.clientDisplay.appendMessage(mid);
                      }
                    Thread.sleep(MSG_CHECK_INTERVAL);
                  } catch (Exception ex)
                  {
                    Logger.getLogger(MainFrame.class.getName()).log(Level.SEVERE, null, ex);
                  }
              } // end while()
        } // end run()
    } // end class MessageGrabber

    /**
     * Creates new form MainFrame
     */
    public MainFrame()
    {
        initComponents();

        // tell client display area to hook up to its
        // data model and display the default "no
        // messages yet" message:
        clientDisplay.initMessageDisplay();

        // We will send messages to and get messages
        // from chatService:
        chatService = new ChatServiceStub();

        // Which User does this client belong to?
        myMaster = new User();
        myMaster.setUserName("Erasmo");
        this.lblLoginName.setText("Logged in as " + myMaster.getUserName());

        // Start the message-fetching loop:
        MessageGrabber msgGrabber = new MessageGrabber();
        Thread tMsg = new Thread(msgGrabber);
        tMsg.start();;

        // Set up the advertising display:
        AdvertisementRotator adRotator = new AdvertisementRotator();
        Thread tAd = new Thread(adRotator);
        tAd.start();

        // Make Send button "fire" when Enter key is pressed:
        this.getRootPane().setDefaultButton(btnSend);

        // Focus on message entry field:
        this.txtOutgoingMessage.requestFocusInWindow();
    }

    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents()
    {

        pnlMain = new javax.swing.JPanel();
        pnlMessageDisplay = new javax.swing.JPanel();
        jScrollPane2 = new javax.swing.JScrollPane();
        clientDisplay = new org.animatedalligator.JListClientDisplay();
        lblLoginName = new javax.swing.JLabel();
        jPanel1 = new javax.swing.JPanel();
        txtOutgoingMessage = new javax.swing.JTextField();
        jLabel1 = new javax.swing.JLabel();
        btnSend = new javax.swing.JButton();
        jMenuBar1 = new javax.swing.JMenuBar();
        mnuFile = new javax.swing.JMenu();
        mniExit = new javax.swing.JMenuItem();
        mnuTools = new javax.swing.JMenu();
        mniOptions = new javax.swing.JMenuItem();
        mnuHelp = new javax.swing.JMenu();
        mniAbout = new javax.swing.JMenuItem();
        jSeparator1 = new javax.swing.JPopupMenu.Separator();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setTitle("Chat Me Up");

        pnlMain.setBackground(new java.awt.Color(204, 255, 204));

        pnlMessageDisplay.setBorder(javax.swing.BorderFactory.createBevelBorder(javax.swing.border.BevelBorder.RAISED));

        jScrollPane2.setAutoscrolls(true);

        clientDisplay.setModel(new DefaultListModel());
        jScrollPane2.setViewportView(clientDisplay);

        javax.swing.GroupLayout pnlMessageDisplayLayout = new javax.swing.GroupLayout(pnlMessageDisplay);
        pnlMessageDisplay.setLayout(pnlMessageDisplayLayout);
        pnlMessageDisplayLayout.setHorizontalGroup(
            pnlMessageDisplayLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 484, Short.MAX_VALUE)
            .addGroup(pnlMessageDisplayLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(pnlMessageDisplayLayout.createSequentialGroup()
                    .addContainerGap()
                    .addComponent(jScrollPane2)
                    .addContainerGap()))
        );
        pnlMessageDisplayLayout.setVerticalGroup(
            pnlMessageDisplayLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 176, Short.MAX_VALUE)
            .addGroup(pnlMessageDisplayLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(pnlMessageDisplayLayout.createSequentialGroup()
                    .addGap(6, 6, 6)
                    .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 164, Short.MAX_VALUE)
                    .addGap(6, 6, 6)))
        );

        javax.swing.GroupLayout pnlMainLayout = new javax.swing.GroupLayout(pnlMain);
        pnlMain.setLayout(pnlMainLayout);
        pnlMainLayout.setHorizontalGroup(
            pnlMainLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(pnlMessageDisplay, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
        );
        pnlMainLayout.setVerticalGroup(
            pnlMainLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(pnlMessageDisplay, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
        );

        lblLoginName.setText("Logged in as ");

        jLabel1.setText("Type your message and press \"Send.\"");

        btnSend.setText("Send");
        btnSend.addActionListener(new java.awt.event.ActionListener()
        {
            public void actionPerformed(java.awt.event.ActionEvent evt)
            {
                btnSendActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
        jPanel1.setLayout(jPanel1Layout);
        jPanel1Layout.setHorizontalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel1Layout.createSequentialGroup()
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(jPanel1Layout.createSequentialGroup()
                        .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                            .addComponent(jLabel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                            .addComponent(txtOutgoingMessage))
                        .addGap(27, 27, 27)
                        .addComponent(btnSend)
                        .addGap(0, 73, Short.MAX_VALUE))
                    .addComponent(lblAds, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                .addContainerGap())
        );
        jPanel1Layout.setVerticalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup()
                .addComponent(jLabel1)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(txtOutgoingMessage, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(btnSend, javax.swing.GroupLayout.PREFERRED_SIZE, 19, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addComponent(lblAds)
                .addContainerGap())
        );

        mnuFile.setText("File");

        mniExit.setText("Exit");
        mniExit.setName("mniExit"); // NOI18N
        mniExit.addActionListener(new java.awt.event.ActionListener()
        {
            public void actionPerformed(java.awt.event.ActionEvent evt)
            {
                mniExitActionPerformed(evt);
            }
        });
        mnuFile.add(mniExit);

        jMenuBar1.add(mnuFile);

        mnuTools.setText("Tools");

        mniOptions.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_O, java.awt.event.InputEvent.CTRL_MASK));
        mniOptions.setText("Options");
        mniOptions.addActionListener(new java.awt.event.ActionListener()
        {
            public void actionPerformed(java.awt.event.ActionEvent evt)
            {
                mniOptionsActionPerformed(evt);
            }
        });
        mnuTools.add(mniOptions);

        jMenuBar1.add(mnuTools);

        mnuHelp.setText("Help");

        mniAbout.setText("About");
        mniAbout.addActionListener(new java.awt.event.ActionListener()
        {
            public void actionPerformed(java.awt.event.ActionEvent evt)
            {
                mniAboutActionPerformed(evt);
            }
        });
        mnuHelp.add(mniAbout);
        mnuHelp.add(jSeparator1);

        jMenuBar1.add(mnuHelp);

        setJMenuBar(jMenuBar1);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(pnlMain, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(lblLoginName, javax.swing.GroupLayout.PREFERRED_SIZE, 236, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap())
            .addGroup(layout.createSequentialGroup()
                .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(0, 36, Short.MAX_VALUE))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addComponent(lblLoginName)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(pnlMain, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap(54, Short.MAX_VALUE))
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

    /**
     * If txtOutgoingMessage text field isn't empty, creates a Message object
     * and calls server's sendMessage() method.
     *
     * @param evt
     */
    private void btnSendActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_btnSendActionPerformed
    {//GEN-HEADEREND:event_btnSendActionPerformed
        if ((this.txtOutgoingMessage.getText() != null)
                && (!this.txtOutgoingMessage.getText().isEmpty()))
          {
            try
              {
                // Construct Message object and send it to server:
                Message msg = new Message();
                msg.setSender(myMaster);
                msg.setContent(this.txtOutgoingMessage.getText());
                // for now, ignore recipients field
                msg.setRecipients(null);
                chatService.sendMessage(msg);
                // set text field back to empty:
                txtOutgoingMessage.setText("");
                // and put focus back into the text field:
                this.txtOutgoingMessage.requestFocusInWindow();
              } catch (Exception ex)
              {
                Logger.getLogger(MainFrame.class.getName()).log(Level.SEVERE, null, ex);
              }
          }
    }//GEN-LAST:event_btnSendActionPerformed

    /**
     * Tools/Options menu item clicked
     *
     * @param evt
     */
    private void mniOptionsActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_mniOptionsActionPerformed
    {//GEN-HEADEREND:event_mniOptionsActionPerformed
        // TODO add your handling code here:
        //JOptionPane.showMessageDialog(null, mnuFile, null, WIDTH, null);
        JOptionPane.showMessageDialog(null, "Option dialog not yet implemented", "Options", JOptionPane.PLAIN_MESSAGE);

    }//GEN-LAST:event_mniOptionsActionPerformed

    /**
     * File/Exit menu item clicked
     *
     * @param evt
     */
    private void mniExitActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_mniExitActionPerformed
    {//GEN-HEADEREND:event_mniExitActionPerformed
        // TODO add your handling code here:
        System.exit(0);
    }//GEN-LAST:event_mniExitActionPerformed

    /**
     * Help/About menu item clicked
     *
     * @param evt
     */
    private void mniAboutActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_mniAboutActionPerformed
    {//GEN-HEADEREND:event_mniAboutActionPerformed
        // TODO add your handling code here:
        JOptionPane.showMessageDialog(null, "About dialog not yet implemented", "About ChatMeUp", JOptionPane.PLAIN_MESSAGE);
    }//GEN-LAST:event_mniAboutActionPerformed

    /**
     * @param args the command line arguments
     */
    public static void main(String args[])
    {
        /* Set the Nimbus look and feel */
        //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
        /* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
         * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html 
         */
        try
          {
            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels())
              {
                if ("Nimbus".equals(info.getName()))
                  {
                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    break;
                  }
              }
          } catch (ClassNotFoundException ex)
          {
            java.util.logging.Logger.getLogger(MainFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
          } catch (InstantiationException ex)
          {
            java.util.logging.Logger.getLogger(MainFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
          } catch (IllegalAccessException ex)
          {
            java.util.logging.Logger.getLogger(MainFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
          } catch (javax.swing.UnsupportedLookAndFeelException ex)
          {
            java.util.logging.Logger.getLogger(MainFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
          }
        //</editor-fold>

        /* Create and display the form */
        java.awt.EventQueue.invokeLater(new Runnable()
        {
            public void run()
            {
                new MainFrame().setVisible(true);
            }
        });
    }
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton btnSend;
    private org.animatedalligator.JListClientDisplay clientDisplay;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JMenuBar jMenuBar1;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JScrollPane jScrollPane2;
    private javax.swing.JPopupMenu.Separator jSeparator1;
    private static final javax.swing.JLabel lblAds = new javax.swing.JLabel();
    private javax.swing.JLabel lblLoginName;
    private javax.swing.JMenuItem mniAbout;
    private javax.swing.JMenuItem mniExit;
    private javax.swing.JMenuItem mniOptions;
    private javax.swing.JMenu mnuFile;
    private javax.swing.JMenu mnuHelp;
    private javax.swing.JMenu mnuTools;
    private javax.swing.JPanel pnlMain;
    private javax.swing.JPanel pnlMessageDisplay;
    private javax.swing.JTextField txtOutgoingMessage;
    // End of variables declaration//GEN-END:variables
}
